[XEN] Work around a Linux PAE issue where it sometimes sets
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 18 Aug 2006 14:24:10 +0000 (15:24 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 18 Aug 2006 14:24:10 +0000 (15:24 +0100)
the top half of a PTE without first clearing the bottom half
(to make the PTE not-present) hence the PTE fails validation
checks.

Also remove dead revalidation function after shadow2 checkin.

Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/mm.c
xen/include/asm-x86/mm.h

index 7cf9ce924a73cd21b4601d8a3913cc1c7b52bec6..7ec237ee8bf5f397da24a35eba8b15008a01dd98 100644 (file)
@@ -3050,56 +3050,6 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
  * Writable Pagetables
  */
 
-/* Re-validate a given p.t. page, given its prior snapshot */
-int revalidate_l1(
-    struct domain *d, l1_pgentry_t *l1page, l1_pgentry_t *snapshot)
-{
-    l1_pgentry_t ol1e, nl1e;
-    int modified = 0, i;
-
-    for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
-    {
-        ol1e = snapshot[i];
-        nl1e = l1page[i];
-
-        if ( likely(l1e_get_intpte(ol1e) == l1e_get_intpte(nl1e)) )
-            continue;
-
-        /* Update number of entries modified. */
-        modified++;
-
-        /*
-         * Fast path for PTEs that have merely been write-protected
-         * (e.g., during a Unix fork()). A strict reduction in privilege.
-         */
-        if ( likely(l1e_get_intpte(ol1e) == (l1e_get_intpte(nl1e)|_PAGE_RW)) )
-        {
-            if ( likely(l1e_get_flags(nl1e) & _PAGE_PRESENT) )
-                put_page_type(mfn_to_page(l1e_get_pfn(nl1e)));
-            continue;
-        }
-
-        if ( unlikely(!get_page_from_l1e(nl1e, d)) )
-        {
-            /*
-             * Make the remaining p.t's consistent before crashing, so the
-             * reference counts are correct.
-             */
-            memcpy(&l1page[i], &snapshot[i],
-                   (L1_PAGETABLE_ENTRIES - i) * sizeof(l1_pgentry_t));
-
-            /* Crash the offending domain. */
-            MEM_LOG("ptwr: Could not revalidate l1 page");
-            domain_crash(d);
-            break;
-        }
-        
-        put_page_from_l1e(ol1e, d);
-    }
-
-    return modified;
-}
-
 static int ptwr_emulated_update(
     unsigned long addr,
     paddr_t old,
@@ -3167,11 +3117,28 @@ static int ptwr_emulated_update(
     nl1e = l1e_from_intpte(val);
     if ( unlikely(!get_page_from_l1e(nl1e, d)) )
     {
-        MEM_LOG("ptwr_emulate: could not get_page_from_l1e()");
-        return X86EMUL_UNHANDLEABLE;
+        if ( (CONFIG_PAGING_LEVELS == 3) &&
+             (bytes == 4) &&
+             !do_cmpxchg &&
+             (l1e_get_flags(nl1e) & _PAGE_PRESENT) )
+        {
+            /*
+             * If this is a half-write to a PAE PTE then we assume that the
+             * guest has simply got the two writes the wrong way round. We
+             * zap the PRESENT bit on the assumption the bottom half will be
+             * written immediately after we return to the guest.
+             */
+            MEM_LOG("ptwr_emulate: fixing up invalid PAE PTE %"PRIpte"\n",
+                    l1e_get_intpte(nl1e));
+            l1e_remove_flags(nl1e, _PAGE_PRESENT);
+        }
+        else
+        {
+            MEM_LOG("ptwr_emulate: could not get_page_from_l1e()");
+            return X86EMUL_UNHANDLEABLE;
+        }
     }
 
-
     /* Checked successfully: do the update (write or cmpxchg). */
     pl1e = map_domain_page(page_to_mfn(page));
     pl1e = (l1_pgentry_t *)((unsigned long)pl1e + (addr & ~PAGE_MASK));
index 0b19fbe7ec2628911d8c2d0e46eb7926be1a2647..106e4860130cfaf5d8d1ef7053fd3dcbe7f0b7d7 100644 (file)
@@ -397,7 +397,6 @@ void memguard_guard_stack(void *p);
 
 int  ptwr_do_page_fault(struct domain *, unsigned long,
                         struct cpu_user_regs *);
-int  revalidate_l1(struct domain *, l1_pgentry_t *, l1_pgentry_t *);
 
 int audit_adjust_pgtables(struct domain *d, int dir, int noisy);